package cn.iocoder.yudao.module.system.service.ai;

import cn.hutool.core.date.LocalDateTimeUtil;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.system.api.social.SocialClientApi;
import cn.iocoder.yudao.module.system.api.social.dto.SocialWxaSubscribeMessageSendReqDTO;
import cn.iocoder.yudao.module.system.controller.admin.ai.ReportController;
import cn.iocoder.yudao.module.system.controller.admin.ai.vo.UserReportPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.ai.vo.UserReportSaveReqVO;
import cn.iocoder.yudao.module.system.controller.admin.answerRecord.vo.AnswerRecordSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.ai.UserReportDO;
import cn.iocoder.yudao.module.system.dal.dataobject.answerRecord.AnswerRecordDO;
import cn.iocoder.yudao.module.system.dal.mysql.answerRecord.AnswerRecordMapper;
import cn.iocoder.yudao.module.system.dal.mysql.userreport.UserReportMapper;
import cn.iocoder.yudao.module.system.service.answerRecord.AnswerRecordService;
import cn.iocoder.yudao.module.system.util.baidu.BaiduAiUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import javax.validation.constraints.NotNull;

import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import cn.iocoder.yudao.module.system.util.baidu.BaiduAiUtils.Version;
import org.apache.commons.lang3.StringUtils;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.USER_REPORT_NOT_EXISTS;


/**
 * AI 报告 Service 实现类
 *
 * @author 芋道源码
 */
@Service
@Validated
@Transactional
public class UserReportServiceImpl implements UserReportService {
    private static final Logger log = LoggerFactory.getLogger(ReportController.class);

    /**
     * 微信订阅消息模板标题 - 报告完成通知
     */
    private static final String WXA_REPORT_COMPLETED = "报告完成通知";

    @Resource
    private UserReportMapper userReportMapper;

    @Resource
    private AnswerRecordService answerRecordService;

    @Resource
    private AnswerRecordMapper answerRecordMapper;

    @Resource
    private SocialClientApi socialClientApi;

    @Override
    public Long createUserReport(UserReportSaveReqVO createReqVO) {
        // 如果没有设置名称，则从问题中提取意向专业名称作为报告名称
        if (StringUtils.isEmpty(createReqVO.getName()) && StringUtils.isNotEmpty(createReqVO.getQuestion())) {
            String name = extractMajorNameFromQuestion(createReqVO.getQuestion());
            createReqVO.setName(name);
        }

        // 插入
        UserReportDO userReport = BeanUtils.toBean(createReqVO, UserReportDO.class);
        userReportMapper.insert(userReport);
        // 返回
        return userReport.getId();
    }

    /**
     * 从问题中提取意向专业名称
     *
     * @param question 问题内容
     * @return 意向专业名称，如果没有找到则返回问题内容本身
     */
    private String extractMajorNameFromQuestion(String question) {
        if (StringUtils.isEmpty(question)) {
            return "用户报告";
        }

        // 尝试使用正则表达式提取“我比较喜欢XXX”或“对XXX感兴趣”中的专业名称
        Pattern pattern1 = Pattern.compile("我比较喜欢([^，。！？]+)");
        Pattern pattern2 = Pattern.compile("对([^，。！？]+)感兴趣");

        Matcher matcher1 = pattern1.matcher(question);
        if (matcher1.find()) {
            return matcher1.group(1);
        }

        Matcher matcher2 = pattern2.matcher(question);
        if (matcher2.find()) {
            return matcher2.group(1);
        }

        // 如果没有找到意向专业，返回问题内容本身
        return question;
    }

    @Override
    public void updateUserReport(UserReportSaveReqVO updateReqVO) {
        // 校验存在
        validateUserReportExists(updateReqVO.getId());
        // 更新
        UserReportDO updateObj = BeanUtils.toBean(updateReqVO, UserReportDO.class);
        userReportMapper.updateById(updateObj);
    }

    @Override
    public void deleteUserReport(Long id) {
        // 校验存在
        validateUserReportExists(id);
        // 删除
        userReportMapper.deleteById(id);
    }

    private void validateUserReportExists(Long id) {
        if (userReportMapper.selectById(id) == null) {
            throw exception(USER_REPORT_NOT_EXISTS);
        }
    }

    @Override
    public UserReportDO getUserReport(Long id) {
        return userReportMapper.selectById(id);
    }

    @Override
    public PageResult<UserReportDO> getUserReportPage(UserReportPageReqVO pageReqVO) {
        return userReportMapper.selectPage(pageReqVO);
    }

    @Override
    public List<UserReportDO> getUserReportByUserId(Long userId, Integer reportId) {
        return userReportMapper.selectList(new QueryWrapper<UserReportDO>().eq("answer_record_id", reportId));
    }


    @Override
    public CompletableFuture<String> createUserReportByCf(UserReportSaveReqVO userReportSaveReqVO) throws ExecutionException, InterruptedException {
        long startTime = System.currentTimeMillis();
        log.info("[createUserReportByCf][开始生成基础版报告: userId={}, answerRecordId={}]",
                userReportSaveReqVO.getUserId(), userReportSaveReqVO.getAnswerRecordId());

        // 获取答题记录
        AnswerRecordDO answerRecord1 = answerRecordService.getAnswerRecord(userReportSaveReqVO.getAnswerRecordId());

        // 如果答题记录存在，更新状态为2（处理中）
        if (answerRecord1 != null) {
            // 使用原子操作更新状态，避免并发问题
            answerRecordMapper.update(null, new LambdaUpdateWrapper<AnswerRecordDO>()
                    .eq(AnswerRecordDO::getId, answerRecord1.getId())
                    .set(AnswerRecordDO::getStatus, 2).set(AnswerRecordDO::getReportName,userReportSaveReqVO.getName()));
        }

        // 创建请求参数的副本，避免异步处理中的数据混淆
        final UserReportSaveReqVO mainReportReqVO = BeanUtils.toBean(userReportSaveReqVO, UserReportSaveReqVO.class);
        final Integer answerRecordId = answerRecord1 != null ? answerRecord1.getId() : null;
        final String originalQuestion = userReportSaveReqVO.getQuestion();

        // 处理学生信息
        long aiStartTime = System.currentTimeMillis();
        CompletableFuture<String> firstResponseFuture = BaiduAiUtils.processStudentInfo(originalQuestion, Version.GUGU);
        log.info("[createUserReportByCf][AI处理开始: userId={}, 耗时={}ms]",
                userReportSaveReqVO.getUserId(), System.currentTimeMillis() - aiStartTime);

        firstResponseFuture.whenComplete((mainReportContent, throwable) -> {
                    if (throwable != null) {
                        log.error("[createUserReportByCf][处理学生信息失败: userId={}]", userReportSaveReqVO.getUserId(), throwable);
                        return;
                    }

                    try {
                        long dbStartTime = System.currentTimeMillis();
                        // 使用主报告请求的副本，避免数据混淆
                        mainReportReqVO.setAnalysisType("1");
                        mainReportReqVO.setContent(mainReportContent);
                        Long reportId = this.createUserReport(mainReportReqVO);

                        log.info("[createUserReportByCf][创建主报告成功: userId={}, reportId={}, 内容长度={}, 数据库操作耗时={}ms]",
                                userReportSaveReqVO.getUserId(), reportId,
                                mainReportContent != null ? mainReportContent.length() : 0,
                                System.currentTimeMillis() - dbStartTime);

                        // 使用原子操作更新状态和报告数量
                        // 注意：reportName已经在接口调用时立即设置，这里只更新状态和报告数量
                        if (answerRecordId != null) {
                            // 使用原子操作更新状态和报告数量，不再更新reportName
                            answerRecordMapper.updateReportCountIncrAndStatus(answerRecordId, 3, null);
                        }

                        // 发送报告完成微信订阅消息
                        if (answerRecordId != null) {
                            sendReportCompletedMessage(mainReportReqVO.getUserId(), mainReportReqVO.getName(), answerRecordId, reportId);
                        }

                        // 处理第二个问题：提取学校和专业信息
                        // 使用同步方式获取学校信息，避免异步嵌套导致的复杂性
                        String schoolInfo = null;
                        try {
                            // 修复：使用主报告内容作为输入来提取学校信息，而不是变量v
                            schoolInfo = BaiduAiUtils.processSchoolInfo(mainReportContent, BaiduAiUtils.Version.SPEED).get();
                            log.info("获取学校信息成功，内容长度: {}", schoolInfo != null ? schoolInfo.length() : 0);

                            // 处理第三个问题：获取所有学校的详细信息
                            // 创建新的线程处理学校详情，避免与主报告处理混淆
                            if (answerRecordId != null && schoolInfo != null) {
                                final String finalSchoolInfo = schoolInfo;
                                CompletableFuture.runAsync(() -> {
                                    try {
                                        processAllSchoolDetails(finalSchoolInfo, Version.PROFESSIONAL, mainReportReqVO.getUserId(), answerRecordId);
                                    } catch (Exception e) {
                                        log.error("处理学校详情失败", e);
                                    }
                                });
                            }
                        } catch (InterruptedException | ExecutionException e) {
                            log.error("获取学校信息失败", e);
                        }
                    } catch (Exception e) {
                        log.error("创建报告过程中发生异常", e);
                    }
                })
                .exceptionally(throwable -> {
                    log.error("生成报告失败", throwable);
                    return null;
                });

        return firstResponseFuture;
    }

    @Override
    public void createUserReportBySd(UserReportSaveReqVO userReportSaveReqVO) {
        long startTime = System.currentTimeMillis();
        log.info("[createUserReportBySd][开始生成专业版报告: userId={}, answerRecordId={}]",
                userReportSaveReqVO.getUserId(), userReportSaveReqVO.getAnswerRecordId());

        // 获取答题记录
        AnswerRecordDO answerRecord1 = answerRecordService.getAnswerRecord(userReportSaveReqVO.getAnswerRecordId());

        // 如果答题记录存在，更新状态为2（处理中）
        if (answerRecord1 != null) {
            // 使用原子操作更新状态，避免并发问题
            // 注意：reportName已经在接口调用时立即设置，这里只更新状态
            answerRecordMapper.update(null, new LambdaUpdateWrapper<AnswerRecordDO>()
                    .eq(AnswerRecordDO::getId, answerRecord1.getId())
                    .set(AnswerRecordDO::getStatus, 2));
        }

        // 创建请求参数的副本，避免异步处理中的数据混淆
        final UserReportSaveReqVO mainReportReqVO = BeanUtils.toBean(userReportSaveReqVO, UserReportSaveReqVO.class);
        final Integer answerRecordId = answerRecord1 != null ? answerRecord1.getId() : null;
        final String originalQuestion = userReportSaveReqVO.getQuestion();

        long aiStartTime = System.currentTimeMillis();
        CompletableFuture<String> firstResponseFuture = BaiduAiUtils.processStudentInfo(originalQuestion, Version.EXPERIENCE);
        log.info("[createUserReportBySd][AI处理开始: userId={}, 耗时={}ms]",
                userReportSaveReqVO.getUserId(), System.currentTimeMillis() - aiStartTime);

        // 使用异步方式处理结果
        firstResponseFuture.whenComplete((content, throwable) -> {
            if (throwable != null) {
                log.error("生成报告失败", throwable);
                return;
            }
            try {
                // 使用主报告请求的副本，避免数据混淆
                mainReportReqVO.setAnalysisType("1");
                mainReportReqVO.setContent(content);
                Long reportId = this.createUserReport(mainReportReqVO);

                log.info("创建体验版报告成功，报告ID: {}, 内容长度: {}", reportId, content != null ? content.length() : 0);

                // 使用原子操作更新状态和报告数量
                if (answerRecordId != null) {
                    // 注意：reportName已经在接口调用时立即设置，这里只更新状态和报告数量
                    // 使用原子操作更新状态和报告数量，不再更新reportName
                    answerRecordMapper.updateReportCountIncrAndStatus(answerRecordId, 3, null);

                    // 发送报告完成微信订阅消息
                    sendReportCompletedMessage(mainReportReqVO.getUserId(), mainReportReqVO.getName(), answerRecordId, reportId);
                }
            } catch (Exception e) {
                log.error("保存报告失败", e);
            }
        });
    }

    @Override
    public void processAllSchoolDetails(String schoolResponse, Version version, @NotNull Long userId, Integer recordId) {
        /**
         * 处理所有学校的详细信息
         * @param schoolResponse JSON格式的学校基本信息
         * @param version 使用的版本
         */
        Integer versionNumber = 1;
        if (version.equals(Version.PROFESSIONAL)) {
            versionNumber = 2;
        }

        // 获取当前的 AnswerRecord
        AnswerRecordDO answerRecord = answerRecordService.getAnswerRecord(recordId);
        if (answerRecord == null) {
            log.error("找不到对应的答题记录，ID: {}", recordId);
            return;
        }

        try {
            // 确保输入的JSON是有效的
            String cleanedJson = BaiduAiUtils.cleanAndValidateJson(schoolResponse);
            if (cleanedJson == null) {
                return;
            }

            ObjectMapper mapper = new ObjectMapper();
            JsonNode jsonNode = mapper.readTree(cleanedJson);
            System.out.println("\n开始获取学校和专业的详细信息：");

            // 获取学校列表数组
            JsonNode schoolList = jsonNode.get("学校列表");
            if (schoolList != null && schoolList.isArray()) {
                for (JsonNode school : schoolList) {
                    String schoolName = school.get("学校名称").asText();
                    System.out.println("\n===============================");
                    System.out.println("正在查询学校：" + schoolName);

                    // 获取学校详细信息
                    UserReportSaveReqVO schoolReportReqVO = new UserReportSaveReqVO();

                    schoolReportReqVO.setAnswerRecordId(recordId);

                    String schoolFeatures = BaiduAiUtils.getSchoolDetails(schoolName, Version.SCHOOL_2);
                    log.info("获取学校详情成功，学校: {}, 内容长度: {}", schoolName, schoolFeatures != null ? schoolFeatures.length() : 0);

                    schoolReportReqVO.setUserId(userId);
                    schoolReportReqVO.setQuestion(schoolName);
                    schoolReportReqVO.setContent(schoolFeatures);
                    schoolReportReqVO.setAnalysisType("2");
                    schoolReportReqVO.setName(schoolName);
                    schoolReportReqVO.setVersion(versionNumber);

                    Long schoolReportId = this.createUserReport(schoolReportReqVO);
                    log.info("创建学校报告成功，学校: {}, 报告ID: {}", schoolName, schoolReportId);

                    // 更新报告数量
                    updateReportCount(answerRecord);
                    // 获取该学校下所有推荐专业的详细信息
                    JsonNode majors = school.get("推荐专业");
                    if (majors != null && majors.isArray()) {
                        for (JsonNode major : majors) {
                            String majorName = major.get("专业名称").asText();
                            System.out.println("\n【专业详细信息】" + majorName);
                            // 获取学校详细信息
//                            List<UserReportDO> userReportDOS1 = userReportMapper.selectList(new QueryWrapper<UserReportDO>().eq("question", schoolName+">"+majorName).eq("analysis_type", "3"));
//                            UserReportSaveReqVO userReportSaveReqVO2 = new UserReportSaveReqVO();
//                            userReportSaveReqVO2.setAnswerRecordId(recordId);
//                            if(userReportDOS1!=null&& !userReportDOS1.isEmpty()){
//                                userReportSaveReqVO2 = BeanUtils.toBean(userReportDOS1.get(0), UserReportSaveReqVO.class);
//                                userReportSaveReqVO2.setUserId(userId);
//                                userReportSaveReqVO2.setId(null);
//                            }else {
//                                String majorFeatures = BaiduAiUtils.getMajorDetails(schoolName, majorName, version);
//                                userReportSaveReqVO2.setUserId(userId);
//                                userReportSaveReqVO2.setQuestion(schoolName+">"+majorName);
//                                userReportSaveReqVO2.setContent(majorFeatures);
//                                userReportSaveReqVO2.setAnalysisType("3");
//
//                            }
//                            userReportSaveReqVO2.setVersion(versionNumber);
//                            this.createUserReport(userReportSaveReqVO2);


                            // 创建专业特色报告
                            UserReportSaveReqVO majorFeatureReqVO = new UserReportSaveReqVO();
                            //获取涉及的就业方向、就业岗位做深入的优势劣势对比分析
                            majorFeatureReqVO.setAnswerRecordId(recordId);

                            String majorFeatures = BaiduAiUtils.getSchoolMajorDetails(schoolName, majorName, Version.MAJOR_3);
                            log.info("获取专业特色成功，学校: {}, 专业: {}, 内容长度: {}",
                                    schoolName, majorName, majorFeatures != null ? majorFeatures.length() : 0);

                            majorFeatureReqVO.setUserId(userId);
                            majorFeatureReqVO.setQuestion(schoolName + ">" + majorName + ">" + "专业特色报告");
                            majorFeatureReqVO.setContent(majorFeatures);
                            majorFeatureReqVO.setAnalysisType("5");
                            majorFeatureReqVO.setName(schoolName + "-" + majorName + "-专业特色");
                            majorFeatureReqVO.setVersion(versionNumber);

                            Long majorFeatureReportId = this.createUserReport(majorFeatureReqVO);
                            log.info("创建专业特色报告成功，学校: {}, 专业: {}, 报告ID: {}",
                                    schoolName, majorName, majorFeatureReportId);

                            // 更新报告数量
                            updateReportCount(answerRecord);

                            //专业就业分析报告
                            UserReportSaveReqVO jobAnalysisReqVO = new UserReportSaveReqVO();
                            jobAnalysisReqVO.setAnswerRecordId(recordId);

                            String majorJobAnalysis = BaiduAiUtils.getSchoolMajorDetails(schoolName, majorName, Version.JOB_2);
                            log.info("获取专业就业分析成功，学校: {}, 专业: {}, 内容长度: {}",
                                    schoolName, majorName, majorJobAnalysis != null ? majorJobAnalysis.length() : 0);

                            jobAnalysisReqVO.setUserId(userId);
                            jobAnalysisReqVO.setQuestion(schoolName + ">" + majorName + ">" + "专业就业分析报告");
                            jobAnalysisReqVO.setContent(majorJobAnalysis);
                            jobAnalysisReqVO.setAnalysisType("4");
                            jobAnalysisReqVO.setName(schoolName + "-" + majorName + "-就业分析");
                            jobAnalysisReqVO.setVersion(versionNumber);

                            Long jobReportId = this.createUserReport(jobAnalysisReqVO);
                            log.info("创建专业就业分析报告成功，学校: {}, 专业: {}, 报告ID: {}",
                                    schoolName, majorName, jobReportId);

                            // 更新报告数量
                            updateReportCount(answerRecord);

                            // 当处理完最后一个专业时，发送报告完成微信订阅消息
                            if (major == majors.get(majors.size() - 1)) {
                                sendReportCompletedMessage(userId, answerRecord.getReportName(), recordId, jobReportId);
                                log.info("处理完所有专业，发送完成通知，学校: {}, 最后专业: {}", schoolName, majorName);
                            }
                        }
                    }
                    System.out.println("\n===============================");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 更新报告数量
     *
     * @param answerRecord 答题记录
     */
    private void updateReportCount(AnswerRecordDO answerRecord) {
        if (answerRecord != null) {
            // 使用原子操作更新报告数量，避免并发问题
            answerRecordMapper.update(null, new LambdaUpdateWrapper<AnswerRecordDO>()
                    .eq(AnswerRecordDO::getId, answerRecord.getId())
                    .setSql("report_count = IFNULL(report_count, 0) + 1"));
        }
    }

    /**
     * 发送报告完成微信订阅消息
     *
     * @param userId 用户ID
     * @param reportName 报告名称
     * @param answerRecordId 答题记录ID
     */
    @Async
    @Override
    public void sendReportCompletedMessage(Long userId, String reportName, Integer answerRecordId, Long reportId) {
        try {
            // 获取当前时间
            String currentTime = LocalDateTimeUtil.formatNormal(LocalDateTime.now());
            // 构建并发送模版消息
            socialClientApi.sendWxaSubscribeMessage(new SocialWxaSubscribeMessageSendReqDTO()
                    .setUserId(userId)
                    .setUserType(UserTypeEnum.MEMBER.getValue())
                    .setTemplateTitle(WXA_REPORT_COMPLETED)
                    .setPage("subpackages/plan/report?id="+reportId) // 报告详情页面
                    .addMessage("phrase4", "已完成") // 报告状态
                    .addMessage("time6", currentTime) // 报告时间
                    .addMessage("short_thing7", "规划报告") // 报告类型
                    .addMessage("time10", currentTime) // 完成时间
                    .addMessage("thing2", reportName) // 项目名称
            );
            log.info("[sendReportCompletedMessage][用户({})报告({})完成消息发送成功]", userId, reportName);
        } catch (Exception e) {
            log.error("[sendReportCompletedMessage][用户({})报告({})完成消息发送失败]", userId, reportName, e);
        }
    }
}
